# asyncio

Асинхронное программирование традиционно относят к темам для "продвинутых". 

Действительно, у новичков часто возникают сложности с практическим освоением асинхронности

```python
from time import sleep, strftime


def fun1(x):
    print(x**2)
    sleep(3)
    print('fun1 завершена')


def fun2(x):
    print(x**0.5)
    sleep(3)
    print('fun2 завершена')


def main():
    fun1(4)
    fun2(4)


print(strftime('%X'))

main()

print(strftime('%X'))


```


Никаких сюрпризов - `fun2` честно ждет пока полностью отработает `fun1` (и быстрая ее часть, и медленная) и только потом начинает выполнять свою работу. 

Весь процесс занимает 3 + 3 = 6 секунд. Строго говоря, чуть больше чем 6 за счет "быстрых" арифметических операций, но в выбранном масштабе разницу уловить невозможно.

Теперь попробуем сделать то же самое, но в асинхронном режиме. 

```python
import asyncio
import time


async def fun1(x):
    print(x**2)
    await asyncio.sleep(3)
    print('fun1 завершена')


async def fun2(x):
    print(x**0.5)
    await asyncio.sleep(3)
    print('fun2 завершена')


async def main():
    task1 = asyncio.create_task(fun1(4))
    task2 = asyncio.create_task(fun2(4))

    await task1
    await task2


print(time.strftime('%X'))

asyncio.run(main())

print(time.strftime('%X'))

```

Сюрприз!
Мгновенно выполнились быстрые части обеих функций и затем через 3 секунды (3, а не 6!) одновременно появились оба текстовых сообщения.
Полное ощущение, что функции выполнились параллельно (на самом деле нет).

А можно аналогичным образом добавить еще одну функцию-соню? Пожалуйста — хоть сто! 

Общее время выполнения программы будет по-прежнему определяться самой "тормознутой" из них.

Что изменилось в коде?

Перед определениями функций появился префикс async. Он говорит интерпретатору, что функция должна выполняться асинхронно.

Вместо привычного time.sleep мы использовали asyncio.sleep. Это "неблокирующий sleep". В рамках функции ведет себя так же, как традиционный, но не останавливает интерпретатор в целом.

Перед вызовом асинхронных функций появился префикс await. Он говорит интерпретатору примерно следующее: "я тут возможно немного потуплю, но ты меня не жди — пусть выполняется другой код, а когда у меня будет настроение продолжиться, я тебе маякну".

На базе функций мы при помощи asyncio.create_task создали задачи (что это такое разберем позже) и запустили все это при помощи asyncio.run